package com.example.demo.service;

import com.example.demo.dto.CreateOrderRequest;
import com.example.demo.dto.OrderDTO;
import com.example.demo.dto.UpdateOrderStatusRequest;
import com.example.demo.entity.OrderEntity;
import com.example.demo.enums.OrderStatusEnum;
import com.example.demo.enums.OrderTypeEnum;
import com.example.demo.enums.PaymentMethodEnum;
import com.example.demo.repository.OrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 订单服务层
 * 
 * 演示功能：
 * 1. 业务逻辑中使用枚举进行状态判断和转换
 * 2. 枚举的业务方法调用
 * 3. 数据传输对象的枚举转换
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class OrderService {
    
    private final OrderRepository orderRepository;
    
    /**
     * 创建订单
     */
    @Transactional
    public OrderDTO createOrder(CreateOrderRequest request) {
        log.info("创建订单，用户ID: {}, 订单类型: {}, 金额: {}", 
                request.getUserId(), request.getType().value(), request.getTotalAmount());
        
        OrderEntity order = new OrderEntity();
        BeanUtils.copyProperties(request, order);
        
        // 生成订单编号
        order.setOrderNo(generateOrderNo());
        
        // 设置默认状态
        if (order.getStatus() == null) {
            order.setStatus(OrderStatusEnum.PENDING_PAYMENT);
        }
        
        OrderEntity savedOrder = orderRepository.save(order);
        
        log.info("订单创建成功，订单ID: {}, 订单编号: {}, 状态: {}", 
                savedOrder.getId(), savedOrder.getOrderNo(), savedOrder.getStatus().value());
        
        return convertToDTO(savedOrder);
    }
    
    /**
     * 根据ID查找订单
     */
    public OrderDTO findById(Long id) {
        OrderEntity order = orderRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("订单不存在：" + id));
        return convertToDTO(order);
    }
    
    /**
     * 根据订单编号查找订单
     */
    public OrderDTO findByOrderNo(String orderNo) {
        OrderEntity order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new RuntimeException("订单不存在：" + orderNo));
        return convertToDTO(order);
    }
    
    /**
     * 根据用户ID查找订单列表
     */
    public List<OrderDTO> findByUserId(Long userId) {
        List<OrderEntity> orders = orderRepository.findByUserIdOrderByCreatedTimeDesc(userId);
        return orders.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 根据订单状态分页查询
     * 演示：枚举作为查询参数的使用
     */
    public Page<OrderDTO> findByStatus(OrderStatusEnum status, int page, int size) {
        Pageable pageable = PageRequest.of(page, size, Sort.by("createdTime").descending());
        Page<OrderEntity> orderPage = orderRepository.findByStatus(status, pageable);
        
        return orderPage.map(this::convertToDTO);
    }
    
    /**
     * 根据订单类型查找订单
     * 演示：枚举作为查询参数的使用
     */
    public List<OrderDTO> findByType(OrderTypeEnum type) {
        List<OrderEntity> orders = orderRepository.findByType(type);
        return orders.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 根据支付方式查找订单
     * 演示：枚举作为查询参数的使用
     */
    public List<OrderDTO> findByPaymentMethod(PaymentMethodEnum paymentMethod) {
        List<OrderEntity> orders = orderRepository.findByPaymentMethod(paymentMethod);
        return orders.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 更新订单状态
     * 演示：枚举业务逻辑和状态转换
     */
    @Transactional
    public OrderDTO updateStatus(Long orderId, UpdateOrderStatusRequest request) {
        OrderEntity order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在：" + orderId));
        
        OrderStatusEnum oldStatus = order.getStatus();
        OrderStatusEnum newStatus = request.getStatus();
        
        log.info("更新订单状态，订单ID: {}, 原状态: {}, 新状态: {}, 原因: {}", 
                orderId, oldStatus.value(), newStatus.value(), request.getReason());
        
        // 状态验证逻辑
        validateStatusTransition(oldStatus, newStatus);
        
        // 更新状态
        order.setStatus(newStatus);
        
        // 根据状态设置相应时间
        LocalDateTime now = LocalDateTime.now();
        switch (newStatus) {
            case PAID:
                order.setPaidTime(now);
                break;
            case SHIPPED:
                order.setShippedTime(now);
                break;
            case COMPLETED:
                order.setCompletedTime(now);
                break;
            case PENDING_PAYMENT:
            case PREPARING:
            case DELIVERED:
            case CANCELLED:
            case REFUNDING:
            case REFUNDED:
                // 这些状态不需要设置特殊时间
                break;
        }
        
        OrderEntity savedOrder = orderRepository.save(order);
        
        log.info("订单状态更新成功，订单ID: {}, 新状态: {}", orderId, newStatus.value());
        
        return convertToDTO(savedOrder);
    }
    
    /**
     * 取消订单
     * 演示：枚举的业务方法使用
     */
    @Transactional
    public OrderDTO cancelOrder(Long orderId, String reason) {
        OrderEntity order = orderRepository.findById(orderId)
                .orElseThrow(() -> new RuntimeException("订单不存在：" + orderId));
        
        // 检查是否可以取消
        if (!order.canCancel()) {
            throw new RuntimeException("订单当前状态不允许取消：" + order.getStatus().value());
        }
        
        log.info("取消订单，订单ID: {}, 原状态: {}, 取消原因: {}", 
                orderId, order.getStatus().value(), reason);
        
        order.setStatus(OrderStatusEnum.CANCELLED);
        order.setRemark(order.getRemark() + " [取消原因：" + reason + "]");
        
        OrderEntity savedOrder = orderRepository.save(order);
        
        log.info("订单取消成功，订单ID: {}", orderId);
        
        return convertToDTO(savedOrder);
    }
    
    /**
     * 获取订单统计信息
     * 演示：枚举在统计查询中的使用
     */
    public List<Object[]> getOrderStatistics() {
        return orderRepository.countByStatusGroup();
    }
    
    /**
     * 查找待处理订单
     * 演示：多个枚举值的查询
     */
    public List<OrderDTO> findPendingOrders() {
        List<OrderStatusEnum> pendingStatuses = List.of(
                OrderStatusEnum.PENDING_PAYMENT,
                OrderStatusEnum.PAID,
                OrderStatusEnum.PREPARING
        );
        
        LocalDateTime oneDayAgo = LocalDateTime.now().minusDays(1);
        List<OrderEntity> orders = orderRepository.findPendingOrders(pendingStatuses, oneDayAgo);
        
        return orders.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());
    }
    
    /**
     * 自动取消过期订单
     * 演示：定时任务中的枚举使用
     */
    @Transactional
    public int cancelExpiredOrders() {
        LocalDateTime expireTime = LocalDateTime.now().minusHours(24); // 24小时未支付自动取消
        List<OrderEntity> expiredOrders = orderRepository.findExpiredPendingOrders(
                OrderStatusEnum.PENDING_PAYMENT, expireTime);
        
        int cancelCount = 0;
        for (OrderEntity order : expiredOrders) {
            if (order.canCancel()) {
                order.setStatus(OrderStatusEnum.CANCELLED);
                order.setRemark(order.getRemark() + " [系统自动取消：支付超时]");
                orderRepository.save(order);
                cancelCount++;
                
                log.info("自动取消过期订单，订单ID: {}, 订单编号: {}", order.getId(), order.getOrderNo());
            }
        }
        
        log.info("自动取消过期订单完成，取消数量: {}", cancelCount);
        return cancelCount;
    }
    
    /**
     * 验证状态转换是否合法
     */
    private void validateStatusTransition(OrderStatusEnum from, OrderStatusEnum to) {
        // 这里可以实现复杂的状态转换逻辑
        if (from.isFinalStatus()) {
            throw new RuntimeException("订单已处于最终状态，不能再次变更：" + from.value());
        }
        
        // 可以根据业务需求添加更多验证逻辑
    }
    
    /**
     * 实体转DTO
     */
    private OrderDTO convertToDTO(OrderEntity entity) {
        OrderDTO dto = new OrderDTO();
        BeanUtils.copyProperties(entity, dto);
        
        // 设置枚举文本字段
        dto.setEnumTexts();
        
        // 设置业务字段
        dto.setCanCancel(entity.canCancel());
        dto.setCanRefund(entity.canRefund());
        dto.setIsOnlinePayment(entity.isOnlinePayment());
        
        return dto;
    }
    
    /**
     * 生成订单编号
     */
    private String generateOrderNo() {
        return "ORD" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }
}
